from copy import deepcopy
from typing import Callable, Optional, Type

from pydantic import create_model

from app.core.generic_types import BaseModelType


def optional(without_fields: Optional[list[str]] = None) -> Callable[[Type[BaseModelType]], Type[BaseModelType]]:
    """
    @optional：将模型的所有字段变为可选的装饰器
    :param without_fields: 不需要变为可选的字段名列表
    :return:
    """
    if without_fields is None:
        without_fields = []

    def wrapper(model: Type[BaseModelType]) -> Type[BaseModelType]:
        # 保留原始模型的配置
        config = model.model_config.copy() if hasattr(model, "model_config") else {}

        # 处理字段
        fields = {}
        for field_name, field_info in model.model_fields.items():
            if field_name in without_fields:
                fields[field_name] = (field_info.annotation, field_info)
            else:
                new_info = deepcopy(field_info)
                new_info.annotation = Optional[field_info.annotation]
                new_info.default = None
                fields[field_name] = (new_info.annotation, new_info)

        # 创建新模型
        return create_model(
            f"Partial{model.__name__}",
            __base__=model,  # 保留原始模型作为基类
            __module__=model.__module__,
            __config__=config,
            **fields,
        )

    return wrapper
